using System.Collections.Generic;
using UnityEngine;

public class AstarPathfinding : SingletonpatternMonoBase<AstarPathfinding>
{
    private List<Grid> path = new List<Grid>();
    private List<Grid> openList = new List<Grid>();
    private List<Grid> closeList = new List<Grid>();



    public List<Grid> Find(Grid starGrid,Grid endGrid)
    {
        Clear();
        openList.Add(starGrid);

        while(openList.Count > 0)
        {
            Grid currentGrid = openList[0];
            for (int i = 1; i < openList.Count; i++)
            {
                if (openList[i].fCost < currentGrid.fCost || openList[i].fCost == currentGrid.fCost && openList[i].hCost < currentGrid.hCost)
                {
                    currentGrid = openList[i];
                }
            }
            openList.Remove(currentGrid);
            closeList.Add(currentGrid);

            if(currentGrid == endGrid)
            {
                RetracePath(endGrid);
                return path;
            }

            foreach(Grid neighbour in GetNeighbours(currentGrid))
            {
                if (!neighbour.IsCanMove || closeList.Contains(neighbour))
                {
                    continue;
                }
                int newCostToNeighbour = currentGrid.gCost + GetDistance(currentGrid, neighbour);
                if (newCostToNeighbour < neighbour.gCost || !openList.Contains(neighbour))
                {
                    neighbour.gCost = newCostToNeighbour;
                    neighbour.hCost = GetDistance(neighbour, endGrid);
                    neighbour.parent = currentGrid;

                    if (!openList.Contains(neighbour))
                    {
                        openList.Add(neighbour);
                    }
                }

            }

        }
        return null;
    }

    void RetracePath(Grid endGrid)
    {
        path.Add(endGrid);
        if (endGrid.parent != null)
        {
            RetracePath(endGrid.parent);
        }
        
    }
    List<Grid> GetNeighbours(Grid grid)
    {
        List<Grid> neighbour = new List<Grid>();
        for (int x = -1; x <= 1; x++)
        {
            for (int y = -1; y <= 1; y++)
            {
                if (Mathf.Abs(x+y)!=1)
                {
                    continue;
                }
                if(GridManager.Instance.IsCanArrive( new Vector2Int(grid.row + x, grid.row + y)))
                {
                    neighbour.Add(GridManager.Instance.grids[grid.row + x, grid.col + y]);

                }
            
            }
        }
        return neighbour;
    }

    int GetDistance(Grid a,Grid b)
    {
        int x = Mathf.Abs(a.row - b.row);
        int y = Mathf.Abs(a.col - b.col);
        return x + y;
    }
    void Clear()
    {
        foreach(Grid grid in GridManager.Instance.grids)
        {
            if (grid != null)
            {
                grid.parent = null;
                grid.gCost = 0;
                grid.hCost = 0;
            }
            
        }
        path.Clear();
        openList.Clear();
        closeList.Clear();
    }

   
}